﻿// -------------------------------------------------------------------------------------------------------------------------------
// <copyright file="IncompatibleMatrixVectorException.cs" company="Exul">
//     Copyright (c) Exul. All rights reserved.
// </copyright>
// <author>
//     Exul
// </author>
// -------------------------------------------------------------------------------------------------------------------------------

namespace ExulLibrary.Mathematics.LinearAlgebra.Exceptions
{
    #region Usings

    using System;
    using System.Globalization;
    using System.Runtime.Serialization;
    using System.Security;

    using ExulLibrary.Mathematics.LinearAlgebra.Properties;

    #endregion

    /// <summary>
    ///     Describes an error when matrix and vector have incompatible dimensions for some operation.
    /// </summary>
    [Serializable]
    public sealed class IncompatibleMatrixVectorException : ArgumentException
    {
        #region Constructors and Destructors

        #region public

        /// <summary>
        ///     Initializes a new instance of the <see cref="IncompatibleMatrixVectorException"/> class.
        /// </summary>
        /// <param name="matrixParamName">
        ///     The name of matrix parameter.
        /// </param>
        /// <param name="matrixRowsCount">
        ///     The rows count of matrix.
        /// </param>
        /// <param name="matrixColumnsCount">
        ///     The columns count of matrix.
        /// </param>
        /// <param name="vectorParamName">
        ///     The name of the vector parameter.
        /// </param>
        /// <param name="vectorLength">
        ///     The length of vector.
        /// </param>
        /// <param name="expectedVectorLength">
        ///     The expected length of vector.
        /// </param>
        public IncompatibleMatrixVectorException(
            string matrixParamName,
            int matrixRowsCount,
            int matrixColumnsCount,
            string vectorParamName,
            int vectorLength,
            int expectedVectorLength)
            : this(
                matrixParamName,
                matrixRowsCount,
                matrixColumnsCount,
                vectorParamName,
                vectorLength,
                expectedVectorLength,
                null)
        {
        }

        /// <summary>
        ///     Initializes a new instance of the <see cref="IncompatibleMatrixVectorException"/> class.
        /// </summary>
        /// <param name="matrixParamName">
        ///     The name of matrix parameter.
        /// </param>
        /// <param name="matrixRowsCount">
        ///     The rows count of matrix.
        /// </param>
        /// <param name="matrixColumnsCount">
        ///     The columns count of matrix.
        /// </param>
        /// <param name="vectorParamName">
        ///     The name of the vector parameter.
        /// </param>
        /// <param name="vectorLength">
        ///     The length of vector.
        /// </param>
        /// <param name="expectedVectorLength">
        ///     The expected length of vector.
        /// </param>
        /// <param name="innerException">
        ///     The inner exception.
        /// </param>
        public IncompatibleMatrixVectorException(
            string matrixParamName,
            int matrixRowsCount,
            int matrixColumnsCount,
            string vectorParamName,
            int vectorLength,
            int expectedVectorLength,
            Exception innerException)
            : base(Resources.MatrixVectorAreIncompatible, vectorParamName, innerException)
        {
            this.MatrixParamName = matrixParamName;
            this.VectorParamName = vectorParamName;
            this.MatrixRowsCount = matrixRowsCount;
            this.MatrixColumnsCount = matrixColumnsCount;
            this.VectorLength = vectorLength;
            this.ExpectedVectorLength = expectedVectorLength;
        }

        #endregion

        #region private

        /// <summary>
        ///     Initializes a new instance of the <see cref="IncompatibleMatrixVectorException"/> class.
        /// </summary>
        /// <param name="info">
        ///     The object that holds the serialized object data.
        /// </param>
        /// <param name="context">
        ///     The contextual information about the source or destination.
        /// </param>
        private IncompatibleMatrixVectorException(SerializationInfo info, StreamingContext context)
            : base(info, context)
        {
            this.MatrixParamName = info.GetString("MatrixParamName");
            this.VectorParamName = info.GetString("VectorParamName");
            this.MatrixRowsCount = info.GetInt32("MatrixRowsCount");
            this.MatrixColumnsCount = info.GetInt32("MatrixColumnsCount");
            this.VectorLength = info.GetInt32("VectorLength");
            this.ExpectedVectorLength = info.GetInt32("ExpectedVectorLength");
        }

        #endregion

        #endregion

        #region Properties

        #region public

        /// <summary>
        ///     Gets the expected length of vector.
        /// </summary>
        /// <value>
        ///     The expected length of vector.
        /// </value>
        public int ExpectedVectorLength
        {
            get;
            private set;
        }

        /// <summary>
        ///     Gets the columns count of matrix.
        /// </summary>
        /// <value>
        ///     The columns count of matrix.
        /// </value>
        public int MatrixColumnsCount
        {
            get;
            private set;
        }

        /// <summary>
        ///     Gets the name of matrix parameter.
        /// </summary>
        /// <value>
        ///     The name of matrix parameter.
        /// </value>
        public string MatrixParamName
        {
            get;
            private set;
        }

        /// <summary>
        ///     Gets the rows count of matrix.
        /// </summary>
        /// <value>
        ///     The rows count of matrix.
        /// </value>
        public int MatrixRowsCount
        {
            get;
            private set;
        }

        /// <summary>
        ///     Gets the length of vector.
        /// </summary>
        /// <value>
        ///     The length of vector.
        /// </value>
        public int VectorLength
        {
            get;
            private set;
        }

        /// <summary>
        ///     Gets the name of vector parameter.
        /// </summary>
        /// <value>
        ///     The name of vector parameter.
        /// </value>
        public string VectorParamName
        {
            get;
            private set;
        }

        #endregion

        #endregion

        #region Overridden Properties

        #region public

        /// <summary>
        ///     Gets the error message and the parameter name, or only the error message if no parameter name is set.
        /// </summary>
        /// <value>
        ///     A text string describing the details of the exception.
        /// </value>
        public override string Message
        {
            get
            {
                return string.Format(
                    CultureInfo.CurrentCulture,
                    base.Message,
                    this.MatrixParamName,
                    this.VectorParamName,
                    this.MatrixRowsCount,
                    this.MatrixColumnsCount,
                    this.VectorLength,
                    this.ExpectedVectorLength);
            }
        }

        #endregion

        #endregion

        #region Overridden Methods

        #region public

        /// <summary>
        ///     Sets the <see cref="SerializationInfo"/> object with the parameter name and additional exception information.
        /// </summary>
        /// <param name="info">
        ///     The object that holds the serialized object data.
        /// </param>
        /// <param name="context">
        ///     The contextual information about the source or destination.
        /// </param>
        /// <exception cref="ArgumentNullException">
        ///     <paramref name="info"/> is <see langword="null"/>.
        /// </exception>
        [SecurityCritical]
        public override void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            base.GetObjectData(info, context);

            info.AddValue("MatrixParamName", this.MatrixParamName);
            info.AddValue("VectorParamName", this.VectorParamName);
            info.AddValue("MatrixRowsCount", this.MatrixRowsCount);
            info.AddValue("MatrixColumnsCount", this.MatrixColumnsCount);
            info.AddValue("VectorLength", this.VectorLength);
            info.AddValue("ExpectedVectorLength", this.ExpectedVectorLength);
        }

        #endregion

        #endregion
    }
}